﻿using HalconDotNet;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DetectApp.Display;

public class LineControl : ROIControl
{
    private readonly Canvas _canvas;
    private readonly Line _line;
    public double K { get => _canvas.ActualWidth / 500.0; }
    private int _docDiameter = 0;

    private bool _isMove;
    private readonly List<Shape> _docEllipse = new();
    private bool _isSCale1;
    private bool _isSCale2;
    private bool _isSCale3;
    private bool _isSCale4;
    private bool _isRotate;
    private Point _startPoint;
    private bool _isVertical;
    private double _startTopLeft;
    private double _startTopUp;
    public string ID { get; set; }
    public LineControl(Canvas canvas, Color color)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        _line = new()
        {
            X1 = 50,
            Y1 = 50,
            X2 = 100 * K,
            Y2 = 100 * K,
            Stroke = new SolidColorBrush(color),
            StrokeThickness = 2 * K,
        };
        _line.MouseEnter += (s, e) =>
        {
            UpdateEllipse(_line, _canvas);
        };
        _line.MouseLeftButtonDown += Line_MouseLeftButtonDown;
        _canvas.Children.Add(_line);
        Canvas.SetLeft(_line, 0);
        Canvas.SetTop(_line, 0);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    public LineControl(Canvas canvas, Point p, Color color, double length, bool isVertical, string iD)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        _isVertical = isVertical;
        if (isVertical)
        {
            _line = new()
            {
                X1 = p.X,
                Y1 = p.Y - length,
                X2 = p.X,
                Y2 = p.Y + length,
                Stroke = new SolidColorBrush(color),
                StrokeThickness = 6,
            };
        }
        else
        {
            _line = new()
            {
                X1 = p.X - length,
                Y1 = p.Y,
                X2 = p.X + length,
                Y2 = p.Y,
                Stroke = new SolidColorBrush(color),
                StrokeThickness = 6,
            };
        }

        _line.MouseEnter += (s, e) =>
        {
            UpdateEllipse(_line, _canvas);
        };
        _line.MouseLeftButtonDown += Line_MouseLeftButtonDown;
        _canvas.Children.Add(_line);
        Canvas.SetLeft(_line, 0);
        Canvas.SetTop(_line, 0);
        ROIChange?.Invoke(this, EventArgs.Empty);
        ID = iD;
    }

    public LineControl(Canvas canvas, ROIParam param)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        _line = new()
        {
            X1 = param.line_start.X,
            Y1 = param.line_start.Y,
            X2 = param.line_end.X,
            Y2 = param.line_end.Y,
            Stroke = new SolidColorBrush(Colors.Blue),
            StrokeThickness = 2 * K,
        };
        _line.MouseEnter += (s, e) =>
        {
            UpdateEllipse(_line, _canvas);
        };
        _line.MouseLeftButtonDown += Line_MouseLeftButtonDown;
        _canvas.Children.Add(_line);
        Canvas.SetLeft(_line, param.Left);
        Canvas.SetTop(_line, param.Top);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    double _startX1, _startY1, _startX2, _startY2;
    private void Line_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _isMove = true;
        _startPoint = Mouse.GetPosition(_canvas);
        _startTopUp = Canvas.GetTop(_line);
        _startTopLeft = Canvas.GetLeft(_line);
        _startX1 = _line.X1;
        _startX2 = _line.X2;
        _startY1 = _line.Y1;
        _startY2 = _line.Y2;
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.LeftButton == MouseButtonState.Released)
        {
            _isMove = false; _isSCale1 = false; _isSCale2 = false; _isSCale3 = false; _isSCale4 = false; _isRotate = false;
        }
        if (!_isSCale1 & !_isSCale2 & !_isSCale3 & !_isSCale4 & !_isMove & !_isRotate)
        {
            bool isClear = true;
            if (_line.IsMouseOver == true) { isClear = false; }
            foreach (var rect in _docEllipse)
            {
                if (rect.IsMouseOver)
                {
                    isClear = false;
                    break;
                }
            }
            if (isClear)
            {
                _docEllipse.ForEach(e => { _canvas.Children.Remove(e); });
                _docEllipse.Clear();
            };
        }
        if (_isMove)
        {
            Point curPoint = Mouse.GetPosition(_canvas);
            var rPoint = curPoint - _startPoint;
            if (_isVertical)
            {
                _line.X1 = rPoint.X + _startX1;
                _line.X2 = rPoint.X + _startX2;
            }
            else
            {
                _line.Y1 = rPoint.Y + _startY1;
                _line.Y2 = rPoint.Y + _startY2;
            }

            //Canvas.SetLeft(_line, _startTopLeft + rPoint.X);
            //Canvas.SetTop(_line, _startTopUp + rPoint.Y);
            UpdateEllipse(_line, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        //if (_isSCale1)
        //{
        //    Point point = Mouse.GetPosition(_line);
        //    _line.X1 = point.X;
        //    _line.Y1 = point.Y;
        //    UpdateEllipse(_line, _canvas);
        //    ROIChange?.Invoke(this, EventArgs.Empty);
        //}
        //if (_isSCale2)
        //{
        //    Point point = Mouse.GetPosition(_line);
        //    _line.X2 = point.X;
        //    _line.Y2 = point.Y;
        //    UpdateEllipse(_line, _canvas);
        //    ROIChange?.Invoke(this, EventArgs.Empty);
        //}
    }

    private void UpdateEllipse(Line line, Canvas canvas)
    {
        //ROIChange?.Invoke(this, EventArgs.Empty);
        _docDiameter = (int)(5 * K);
        Brush fillBrush = new SolidColorBrush(Colors.Blue);
        double opacityK = 1;
        _docEllipse.ForEach(e => { canvas.Children.Remove(e); });
        _docEllipse.Clear();
        Point point = line.TranslatePoint(new Point(line.X1, line.Y1), canvas);
        Ellipse circle1 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle1, point.X - _docDiameter / 2);
        Canvas.SetTop(circle1, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle1);
        _docEllipse.Add(circle1);

        circle1.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale1 = true;
            _startPoint = new Point(line.X1, line.Y1);
        };
        circle1.MouseLeftButtonUp += (s, e) => { _isSCale1 = false; };

        point = line.TranslatePoint(new Point(line.X2, line.Y2), canvas);
        Ellipse circle2 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle2, point.X - _docDiameter / 2);
        Canvas.SetTop(circle2, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle2);
        _docEllipse.Add(circle2);
        circle2.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale2 = true;
            _startPoint = new Point(line.X2, line.Y2);
        };
        circle2.MouseLeftButtonUp += (s, e) => { _isSCale2 = false; };
    }

    public override HRegion? GetRegion()
    {
        HRegion? region = new();
        region.GenRegionLine(_line.Y1, _line.X1, _line.Y2, _line.X2);
        return region;
    }

    public Line? GetLine()
    {

        return _line;
    }

    public override ROIInfo GetROI()
    {
        ROIInfo roi = new();
        Point startPoint = _line.TranslatePoint(new Point(_line.X1, _line.Y1), _canvas);
        Point endPoint = _line.TranslatePoint(new Point(_line.X2, _line.Y2), _canvas);
        roi.ROIType = ROIType.直线;
        roi.StartX = startPoint.X;
        roi.StartY = startPoint.Y;
        roi.EndX = endPoint.X;
        roi.EndY = endPoint.Y;
        return roi;
    }

    public override ROIParam GetParam()
    {
        ROIParam param = new() { ROIType = ROIType.直线 };
        param.line_start = new Point(_line.X1, _line.Y1);
        param.line_end = new Point(_line.X2, _line.Y2);
        param.Left = Canvas.GetLeft(_line);
        param.Top = Canvas.GetTop(_line);
        return param;
    }

    public override void Remove()
    {
        _canvas.Children.Remove(_line);
    }
}